﻿// <copyright file="ConsoleAnalytics.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-06-04</date>
// <summary>ConsoleAnalytics class definition</summary>

namespace Microsoft.WebAnalytics.Behaviors
{
    using System;
    using System.ComponentModel.Composition;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Windows;
#if SILVERLIGHT && !WINDOWS_PHONE && !XBOX
    using System.Windows.Browser;
#endif
    using System.Windows.Interactivity;
    using Microsoft.WebAnalytics;

    /// <summary>
    /// <img src="../media/Microsoft.WebAnalytics.Behaviors.ConsoleAnalytics.24x24.png"/> 
    /// Track an event in the debug console for IE8, Chrome, FireFox FireBug, and Safari
    /// </summary>
    public class ConsoleAnalytics : Behavior<FrameworkElement>
    {
        /// <summary>
        /// Initializes a new instance of the ConsoleAnalytics class.
        /// </summary>
        public ConsoleAnalytics()
        {
#if SILVERLIGHT
            this.IsConsoleAvailable = true;
#endif
        }

        #region Properties
        /// <summary>
        /// Gets or sets the events
        /// </summary>
        [Import]
        public WebAnalyticsEvents Events { get; set; }

#if SILVERLIGHT
        /// <summary>
        /// Gets a value indicating whether the browser console is available
        /// </summary>
        public bool IsConsoleAvailable { get; private set; }

        /// <summary>
        /// Gets a value indicating whether to use the console.log property
        /// </summary>
        public bool ShouldUseConsoleProperty { get; private set; }
#endif
        #endregion

        #region Methods
        /// <summary>
        /// Initialize the imported parts and attache the TrackEvent handler
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();
#if WINDOWS_PHONE
            CompositionInitializer.SatisfyImports(this);
#else
            PartInitializer.SatisfyImports(this);
#endif
            this.Events.TrackEvent += new System.EventHandler<AnalyticsEventArgs>(this.Events_TrackEvent);

#if SILVERLIGHT && !WINDOWS_PHONE && !XBOX
            if (HtmlPage.IsEnabled)
            {
                var window = HtmlPage.Window;

                this.IsConsoleAvailable = (bool)window.Eval("typeof(console) != 'undefined' && typeof(console.log) != 'undefined'");
            }
            else
            {
                this.IsConsoleAvailable = false;
            }
#endif

#if !SL3
            this.AssociatedObject.Unloaded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
            {
                System.Windows.Interactivity.Interaction.GetBehaviors(this.AssociatedObject).Remove(this);
            });
#endif
        }

        /// <summary>
        /// Detach the TrackEvent() handler
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.Events.TrackEvent -= new System.EventHandler<AnalyticsEventArgs>(this.Events_TrackEvent);
        }
        #endregion

        #region Implementation
#if SILVERLIGHT && !WINDOWS_PHONE && !XBOX
        /// <summary>
        /// Log to the Console property
        /// </summary>
        /// <param name="status">the status message</param>
        /// <remarks>This is for Google Chrome on Windows</remarks>
        private static void LogToConsole(string status)
        {
            var consoleProperty = HtmlPage.Window.GetProperty("console") as ScriptObject;

            if (consoleProperty != null)
            {
                consoleProperty.Invoke("log", status);
            }
        }
#endif
        /// <summary>
        /// Set the status bar event
        /// </summary>
        /// <param name="sender">the event tracker</param>
        /// <param name="e">the anlalytics event arguments</param>
        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.String.Format(System.IFormatProvider,System.String,System.Object[])", Justification = "Incorrect alert: the result is not being ignored.")]
        private void Events_TrackEvent(object sender, AnalyticsEventArgs e)
        {
            string status = string.Format(
                CultureInfo.InvariantCulture,
                "{0}: {1}, {2}, {3}",
                e.AnalyticsEvent.Name,
                e.AnalyticsEvent.ObjectName,
                e.AnalyticsEvent.Value,
                e.AnalyticsEvent.ActionValue);

            System.Diagnostics.Debug.WriteLine(status);

#if SILVERLIGHT && !WINDOWS_PHONE && !XBOX
            if (this.IsConsoleAvailable)
            {
                if (this.ShouldUseConsoleProperty)
                {
                    LogToConsole(status);
                }
                else
                {
                    var console = HtmlPage.Window.Eval("console.log") as ScriptObject;

                    if (console != null)
                    {
                        try
                        {
                            console.InvokeSelf(status);
                        }
                        catch (InvalidOperationException)
                        {
                            //// In Google Chrome

                            LogToConsole(status);

                            this.ShouldUseConsoleProperty = true;
                        }
                    }
                }
            }
#endif
        }

        #endregion
    }
}
